using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ShouldIt.Core;

namespace ShouldIt.Clr.Fluent
{
    public class Count<T, TShould> where TShould : ShouldEnumerableBase<T, TShould>
    {
        private ShouldEnumerableBase<T, TShould> should;
        private readonly IAssertProvider assertProvider;

        public Count(ShouldEnumerableBase<T, TShould> should, IAssertProvider assertProvider)
        {
            this.should = should;
            this.assertProvider = assertProvider;
        }

        public IEnumerable<T> Exactly(int expectedCount)
        {
            if (should.Negate)
            {
                assertProvider.AreNotEqual(expectedCount, should.Target.Count());
            }
            else
            {
                assertProvider.AreEqual(expectedCount, should.Target.Count());
            }
            return should.Target;
        }

        public IEnumerable<T> AtLeast(int expectedMinimumCount)
        {
            if (should.Negate)
            {
                assertProvider.GreaterOrEqual(expectedMinimumCount, should.Target.Count());
            }
            else
            {
                assertProvider.GreaterOrEqual(should.Target.Count(), expectedMinimumCount);
            }
            return should.Target;
        }

        public IEnumerable<T> NoMoreThan(int expectedMaximumCount)
        {
            if (should.Negate)
            {
                assertProvider.GreaterOrEqual(should.Target.Count(), expectedMaximumCount);
            }
            else
            {
                assertProvider.GreaterOrEqual(expectedMaximumCount, should.Target.Count());
            }
            return should.Target;
        }

        public IEnumerable<T> Zero()
        {
            if (should.Negate)
            {
                assertProvider.AreNotEqual(0, should.Target.Count());
            }
            else
            {
                assertProvider.AreEqual(0, should.Target.Count());
            }
            return should.Target;
        }
    }

    public class Count
    {
        private ShouldCollection should;
        private IAssertProvider assertProvider;

        public Count(ShouldCollection should, IAssertProvider assertProvider)
        {
            this.should = should;
            this.assertProvider = assertProvider;
        }

        public ICollection Exactly(int expectedCount)
        {
            if (should.Negate)
            {
                assertProvider.AreNotEqual(expectedCount, should.Target.Count);
            }
            else
            {
                assertProvider.AreEqual(expectedCount, should.Target.Count);
            }
            return should.Target;
        }

        public ICollection AtLeast(int expectedMinimumCount)
        {
            if (should.Negate)
            {
                assertProvider.GreaterOrEqual(expectedMinimumCount, should.Target.Count);
            }
            else
            {
                assertProvider.GreaterOrEqual(should.Target.Count, expectedMinimumCount);
            }
            return should.Target;
        }

        public ICollection NoMoreThan(int expectedMaximumCount)
        {
            if (should.Negate)
            {
                assertProvider.GreaterOrEqual(should.Target.Count, expectedMaximumCount);
            }
            else
            {
                assertProvider.GreaterOrEqual(expectedMaximumCount, should.Target.Count);
            }
            return should.Target;
        }

        public ICollection Zero()
        {
            if (should.Negate)
            {
                assertProvider.AreNotEqual(0, should.Target.Count);
            }
            else
            {
                assertProvider.AreEqual(0, should.Target.Count);
            }
            return should.Target;
        }
    }
}